#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdint.h>

#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>

#define LOCAL_IP     "192.168.2.76"
#define LOCAL_PORT   9000
#define BUF_SIZE     1024

/** 共享内存块和 */
#define SHM_NAME "train_share_mem"
#define SHM_SIZE 4096


typedef struct {
    uint8_t  TID;       // TID_MVB_PD_DATA
    uint8_t  fcode;     // 端口字节大小 0,1,2,3,4
    uint16_t pdPort;    // 端口号
    uint8_t  pdData[32];// 数据区
} mvb_data_full;

#define MVB_HEADER_0 0x21
#define MVB_HEADER_1 0x04
#define HEADER_SIZE  (sizeof(uint8_t) * 2)           // TID + fcode
#define ADDR_SIZE    (sizeof(uint16_t))              // pdPort
#define LEN_SIZE     (sizeof(mvb_data_full))         // 整个数据结构长度
#define CRC_SIZE     (sizeof(uint16_t))              // 假设CRC为2字节



// 定义数据类型枚举
typedef enum {
    DATA_TYPE_WEIGHT = 0,         // 车载重量数据
    DATA_TYPE_CLOCK,              // 时钟数据
    DATA_TYPE_AIR_CONSUMPTION,    // 空调能耗数据
    DATA_TYPE_A1_TEMP_HUMI,       // A1车厢温湿度数据
    DATA_TYPE_B1_TEMP_HUMI,       // B1车厢温湿度数据
    DATA_TYPE_B2_TEMP_HUMI,       // B2车厢温湿度数据
    DATA_TYPE_A2_TEMP_HUMI,       // A2车厢温湿度数据
    DATA_TYPE_A1_VALVE,           // A1车厢阀门状态
    DATA_TYPE_B1_VALVE,           // B1车厢阀门状态
    DATA_TYPE_B2_VALVE,           // B2车厢阀门状态
    DATA_TYPE_A2_VALVE,           // A2车厢阀门状态
    DATA_TYPE_UNKNOWN             // 未知数据类型
} DataType;

// 车载重量结构体，包含A1, B1, B2, A2重量和节能状态
typedef struct {
    uint16_t a1_weight;
    uint16_t b1_weight;
    uint16_t b2_weight;
    uint16_t a2_weight;
    uint8_t  is_energy_saving; // 0: 否, 1: 是
} WeightData;

// 时钟结构体，年、月、日、时、分、秒分别用uint8_t存储
typedef struct {
    uint8_t year;   // 年
    uint8_t month;  // 月
    uint8_t day;    // 日
    uint8_t hour;   // 时
    uint8_t minute; // 分
    uint8_t second; // 秒
    uint8_t reserved1; // 保留
    uint8_t reserved2; // 保留
} ClockData;

// 空调能耗结构体，包含司机室、A1、B1、B2、A2、尾端司机室、总能耗
typedef struct {
    float driver_cab_consumption;      // 司机室能耗
    float a1_consumption;              // A1能耗
    float b1_consumption;              // B1能耗
    float b2_consumption;              // B2能耗
    float a2_consumption;              // A2能耗
    float tail_driver_cab_consumption; // 尾端司机室能耗
    float total_consumption;           // 空调总能耗
} AirConsumptionData;

// 列车温湿度结构体，包含室外温度、客室湿度、客室PM2.5、客室PMTOVC、客室二氧化碳浓度
typedef struct {
    uint8_t outdoor_temp;      // 室外温度
    uint8_t room_humidity;     // 客室湿度
    uint16_t room_pm25;        // 客室PM2.5
    uint16_t room_pmtovc;      // 客室PMTOVC
    uint16_t room_co2;         // 客室二氧化碳浓度
} TempHumiData;

// 控制阀数据结构体，包含客室温度、回风温度、新风温度，以及16个新风阀开度状态位
typedef struct {
    uint8_t room_temp;         // 客室温度
    uint8_t reserved0; // 保留一个uint8_t的空位置
    uint8_t return_air_temp;   // 客室回风温度
    uint8_t reserved1; // 保留一个uint8_t的空位置
    uint8_t fresh_air_temp;    // 客室新风温度
    uint8_t reserved2; // 保留一个uint8_t的空位置
    uint8_t group_1;
    uint8_t group_2;
    uint16_t reserved3; // 16个新风阀开度状态位，每一位代表一个阀门的开关状态
    uint16_t reserved4; // 16个新风阀开度状态位，每一位代表一个阀门的开关状态
    uint16_t fresh_valve_status; // 16个新风阀开度状态位，每一位代表一个阀门的开关状态
    uint16_t fresh_valve_status2;
} ValveData;

// 定义全局数据结构
typedef struct {
    WeightData weight;                 // 车载重量
    ClockData clock;                   // 时钟
    AirConsumptionData air_consumption;// 空调能耗
    TempHumiData a1_temp_humi;         // A1温湿度
    TempHumiData b1_temp_humi;         // B1温湿度
    TempHumiData b2_temp_humi;         // B2温湿度
    TempHumiData a2_temp_humi;         // A2温湿度
    ValveData a1_valve;                // A1控制阀数据
    ValveData b1_valve;                // B1控制阀数据
    ValveData b2_valve;                // B2控制阀数据
    ValveData a2_valve;                // A2控制阀数据
} TrainData;

// 全局变量
TrainData g_train_data;

// 写操作函数
void write_train_data(DataType type, void *data)
{
    switch (type) {
        case DATA_TYPE_WEIGHT: // 车载重量
            memcpy(&g_train_data.weight, data, sizeof(WeightData));
            break;
        case DATA_TYPE_CLOCK: // 时钟
            memcpy(&g_train_data.clock, data, sizeof(ClockData));
            printf("g_train_data.clock: year=%u, month=%u, day=%u, hour=%u, minute=%u, second=%u\n",
                   g_train_data.clock.year,
                   g_train_data.clock.month,
                   g_train_data.clock.day,
                   g_train_data.clock.hour,
                   g_train_data.clock.minute,
                   g_train_data.clock.second);
            break;
        case DATA_TYPE_AIR_CONSUMPTION: // 空调能耗
            memcpy(&g_train_data.air_consumption, data, sizeof(AirConsumptionData));
            // 以十六进制形式输出 g_train_data.air_consumption 的内容
            printf("g_train_data.air_consumption: driver_cab_consumption=%f, a1_consumption=%f, b1_consumption=%f, b2_consumption=%f, a2_consumption=%f, tail_driver_cab_consumption=%f, total_consumption=%f\n",
                   g_train_data.air_consumption.driver_cab_consumption,
                   g_train_data.air_consumption.a1_consumption,
                   g_train_data.air_consumption.b1_consumption,
                   g_train_data.air_consumption.b2_consumption,
                   g_train_data.air_consumption.a2_consumption,
                   g_train_data.air_consumption.tail_driver_cab_consumption,
                   g_train_data.air_consumption.total_consumption);
            break;
        case DATA_TYPE_A1_TEMP_HUMI: // A1温湿度
            memcpy(&g_train_data.a1_temp_humi, data, sizeof(TempHumiData));
            break;
        case DATA_TYPE_B1_TEMP_HUMI: // B1温湿度
            memcpy(&g_train_data.b1_temp_humi, data, sizeof(TempHumiData));
            break;
        case DATA_TYPE_B2_TEMP_HUMI: // B2温湿度
            memcpy(&g_train_data.b2_temp_humi, data, sizeof(TempHumiData));
            break;
        case DATA_TYPE_A2_TEMP_HUMI: // A2温湿度
            memcpy(&g_train_data.a2_temp_humi, data, sizeof(TempHumiData));
            break;
        case DATA_TYPE_A1_VALVE: // A1控制阀
            memcpy(&g_train_data.a1_valve, data, sizeof(ValveData));
            break;
        case DATA_TYPE_B1_VALVE: // B1控制阀
            memcpy(&g_train_data.b1_valve, data, sizeof(ValveData));
            break;
        case DATA_TYPE_B2_VALVE: // B2控制阀
            memcpy(&g_train_data.b2_valve, data, sizeof(ValveData));
            break;
        case DATA_TYPE_A2_VALVE: // A2控制阀
            memcpy(&g_train_data.a2_valve, data, sizeof(ValveData));
            break;
        default:
            // 未知类型，不做处理
            break;
    }

    
    // 以十六进制形式输出 g_train_data 的内容
    unsigned char *ptr = (unsigned char *)&g_train_data;
    size_t len = sizeof(g_train_data);
    printf("g_train_data hex dump (%zu bytes):\n", len);
    for (size_t i = 0; i < len; ++i) {
        printf("%02X ", ptr[i]);
        if ((i + 1) % 16 == 0)
            printf("\n");
    }
    if (len % 16 != 0) {
        printf("\n");
    }
}


//此函数根据不同的端口， 映射不同的数据结构， 并得到的列车参数内容
void port_action(uint16_t pdPort_be, uint8_t *data)
{
    printf("4444-pdPort_be = %d\n", pdPort_be);
    
    // 声明所有需要的变量
    uint8_t weight_data_segment[8];
    uint8_t clock_data_segment[6];
    uint8_t ac_energy_data_segment[28];
    uint8_t a1_temp_humidity_data_segment[8];
    uint8_t b1_temp_humidity_data_segment[8];
    uint8_t b2_temp_humidity_data_segment[8];
    uint8_t a2_temp_humidity_data_segment[8];
    uint8_t a1_valve_data_segment[16];
    uint8_t b1_valve_data_segment[16];
    uint8_t b2_valve_data_segment[16];
    uint8_t a2_valve_data_segment[16];
    
    switch (pdPort_be) {
        case 249: {
            printf("pdPort_be = 【车载重量】\n");
            // 取data的第9至第16个字节（即data[8]到data[15]），传入write_train_data
            memcpy(weight_data_segment, data + 8, 8);
            write_train_data(DATA_TYPE_WEIGHT, weight_data_segment);
            break;
        }
        case 255: {
            // 取data的第1至第6个字节（即data[0]到data[5]），传入write_train_data
            memcpy(clock_data_segment, data, 6);
            write_train_data(DATA_TYPE_CLOCK, clock_data_segment);
            break;
        }
        case 39: {
            memcpy(ac_energy_data_segment, data, 28);
            write_train_data(DATA_TYPE_AIR_CONSUMPTION, ac_energy_data_segment);
            printf("pdPort_be = 【空调能耗】\n");
            break;
        }
        case 401: {
            memcpy(a1_temp_humidity_data_segment, data + 4, 8);
            write_train_data(DATA_TYPE_A1_TEMP_HUMI, a1_temp_humidity_data_segment);
            printf("pdPort_be = 【列车A1 温湿度数据】\n");
            break;
        }
        case 657: {
            memcpy(b1_temp_humidity_data_segment, data + 4, 8);
            write_train_data(DATA_TYPE_B1_TEMP_HUMI, b1_temp_humidity_data_segment);
            printf("pdPort_be = 【列车B1温湿度数据】\n");
            break;
        }
        case 913: {
            memcpy(b2_temp_humidity_data_segment, data + 4, 8);
            write_train_data(DATA_TYPE_B2_TEMP_HUMI, b2_temp_humidity_data_segment);
            printf("pdPort_be = 【列车B2温湿度数据】\n");
            break;
        }
        case 1169: {
            memcpy(a2_temp_humidity_data_segment, data + 4, 8);
            write_train_data(DATA_TYPE_A2_TEMP_HUMI, a2_temp_humidity_data_segment);
            printf("pdPort_be = 【列车A2温湿度数据】\n");
            break;
        }
        case 400: {
            memcpy(a1_valve_data_segment, data + 2, 16);
            write_train_data(DATA_TYPE_A1_VALVE, a1_valve_data_segment);
            printf("pdPort_be = 【列车A1 控制阀数据】\n");
            break;
        }
        case 656: {
            memcpy(b1_valve_data_segment, data + 2, 16);
            write_train_data(DATA_TYPE_B1_VALVE, b1_valve_data_segment);
            printf("pdPort_be = 【列车B1 控制阀数据】\n");
            break;
        }
        case 912: {
            memcpy(b2_valve_data_segment, data + 2, 16);
            write_train_data(DATA_TYPE_B2_VALVE, b2_valve_data_segment);
            printf("pdPort_be = 【列车B2 控制阀数据】\n");
            break;
        }
        case 1168: {
            memcpy(a2_valve_data_segment, data + 2, 16);
            write_train_data(DATA_TYPE_A2_VALVE, a2_valve_data_segment);
            printf("pdPort_be = 【列车A2 控制阀数据】\n");
            break;
        }
        default:
            printf("pdPort_be = %d\n", pdPort_be);
    }
}


int main() {
    int sockfd;
    struct sockaddr_in localaddr, remoteaddr;
    char buffer[BUF_SIZE];
    socklen_t addr_len = sizeof(remoteaddr);
    ssize_t n;

    // 创建UDP套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&localaddr, 0, sizeof(localaddr));
    localaddr.sin_family = AF_INET;
    localaddr.sin_addr.s_addr = inet_addr(LOCAL_IP);
    localaddr.sin_port = htons(LOCAL_PORT);
    if (bind(sockfd, (struct sockaddr*)&localaddr, sizeof(localaddr)) < 0) {
        perror("bind error");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    printf("等待接收MVB协议UDP数据...\n");
    while (1) {
    
        n = recvfrom(sockfd, buffer, BUF_SIZE, 0, (struct sockaddr*)&remoteaddr, &addr_len);
        if (n < 0) {
            perror("recvfrom error");
            break;
        }
        // printf("收到数据(%zd字节): ", n);
        // for (ssize_t i = 0; i < n; ++i) {
        //     printf("%02X ", (unsigned char)buffer[i]);
        // }

        // 将接收到的数据映射为 mvb_data_full 结构体
        printf("mvb_data_full 结构体大小: %zu\n", sizeof(mvb_data_full));
        
        // mvb_data_full *mvb_data = (mvb_data_full *)buffer;

        mvb_data_full mvb_data_zero = {0};
        memcpy(&mvb_data_zero, buffer, sizeof(mvb_data_full));
        mvb_data_full *mvb_data = &mvb_data_zero;

         for (size_t i = 0; i < sizeof(mvb_data_full); ++i) {
            printf("%02X ", (unsigned char)buffer[i]);
        }
        
        // 你可以在这里访问 mvb_data 的各个字段，例如:
        // 修正：假设 mvb_data_full 结构体中 pdPort 字段不是 header 指针下的成员，而是直接成员
        // 正确输出 pdPort 的数值，假设 pdPort 是 uint16_t 类型，避免类型提升导致的错误

        uint16_t pdPort_be = ((uint8_t*)&mvb_data->pdPort)[0] << 8 | ((uint8_t*)&mvb_data->pdPort)[1];

        printf("mvb_data->pdPort (10进制) = %d\n", pdPort_be);
        printf("mvb_data->pdPort (十六进制): ");
        // 假设 pdPort 是一个非数组类型（如 uint16_t 或 uint32_t），逐字节打印
        char pdPort_hex[sizeof(mvb_data->pdPort) * 2 + 1] = {0};
        for (size_t i = 0; i < sizeof(mvb_data->pdPort); ++i) {
            sprintf(&pdPort_hex[i * 2], "%02X", ((unsigned char*)&mvb_data->pdPort)[i]);
        }
        printf("%s\n", pdPort_hex);
        
        // 优化switch：用结构体数组映射pdPort_be到描述，查找更高效，便于维护
        typedef struct {
            uint16_t port;
            const char *desc;
        } PdPortDesc;

        static const PdPortDesc pdPortDescTable[] = {
            {0x00F9, "【车载重量】"},
            {0x00FF, "【时钟】"},
            {0x0027, "【空调能耗】"},
            {0x0191, "【列车温湿度数据】"},
            {0x0291, "【列车温湿度数据】"},
            {0x0391, "【列车温湿度数据】"},
            {0x0491, "【列车温湿度数据】"},
            {0x0190, "【列车数据】"},
            {0x0290, "【列车数据】"},
            {0x0390, "【列车数据】"},
            {0x0490, "【列车数据】"},
        };

        const char *desc = NULL;
        for (size_t i = 0; i < sizeof(pdPortDescTable)/sizeof(pdPortDescTable[0]); ++i) {
            if (pdPort_be == pdPortDescTable[i].port) {
                desc = pdPortDescTable[i].desc;
                
                //执行端口数据处理动作
                port_action(pdPort_be, mvb_data->pdData);
                break;
            }
        }

        if (desc) {
            printf("pdPort_be = %s\n", desc);
        } else {
            printf("pdPort_be = %d\n", pdPort_be);
        }

        //读取的到数据 映射到 中心数据集合 ，条件当前的情况组合
            //持续时长
            //温度条件
            //湿度条件
            //重量条件
            //是否紧急模式
            //空调能耗条件
            //列车数据条件
            //列车温湿度数据条件
            //列车数据条件

        //异步脚本来试试
            //存储到同一个内存区块
            //异步数据调整，流数据处理更新
            //工况温判定
            //工况指令下发

        //数据封装下发，下发到低碳节能平台， 平台下发到设备
            //上行发送数据
            //下行存储数据 状态判定

        printf("\n");
        //端口重置 
        pdPort_be   = 0x0000;
        //释放buffer 空间后续使用
        memset(buffer, 0, sizeof(buffer));
    }
    close(sockfd);
    
    return 0;
}


int setDataToMemory(char *message) {
     // 1. 创建共享内存对象
    int shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1) {
        perror("shm_open failed");
        exit(EXIT_FAILURE);
    }

    // 2. 设置共享内存大小
    if (ftruncate(shm_fd, SHM_SIZE) == -1) {
        perror("ftruncate failed");
        exit(EXIT_FAILURE);
    }

    // 3. 映射共享内存
    char *shm_ptr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (shm_ptr == MAP_FAILED) {
        perror("mmap failed");
        exit(EXIT_FAILURE);
    }

    // 4. 写入数据到共享内存
    if (message == NULL) {
        message = "Hello from Process A!";
    }
    sprintf(shm_ptr, "%s", message);
    printf("[A] Wrote to shared memory: %s\n", message);

    // 5. 等待用户输入后清理
    printf("[A] Press Enter to unlink shared memory...\n");
    getchar();

    // 6. 清理资源
    munmap(shm_ptr, SHM_SIZE);
    shm_unlink(SHM_NAME);
    close(shm_fd);

    return 0;
}







